/// ident, tt, lifetime 在匹配后生成的 AST 是清楚的, 其他的不行.
/// 所以这里可以继续调用 impl_redis_value_and_args
/// TODO: 这里如果同时存在泛型和声明周期的话, 会把声明周期当成泛型处理, 导致报错
///
/// [声明式宏泛型处理](https://zhuanlan.zhihu.com/p/568503023)
#[macro_export]
macro_rules! redis_args {
    ($(#[$meta:meta])* $v: vis struct $name: ident $(<$($generic:tt $( : $trait_t: tt $( :: $trait_t2: tt)* $(+ $trait_t3: tt $( :: $trait_t4: tt)*)*)?),+>)? {
        $($(#[$field_meta:meta])*
        $field_vis:vis $field_name:ident: $field_ty:ty,)*$(,)?
    }) => {
        $(#[$meta])*
        $v struct $name $(<$($generic $( : $trait_t $( :: $trait_t2)* $(+ $trait_t3 $( :: $trait_t4)*)*)?),+>)? {
            $(
            $(#[$field_meta])*
             $field_vis $field_name: $field_ty,
            )*
        }

        impl$(<$($generic $( : $trait_t $( :: $trait_t2)* $(+ $trait_t3 $( :: $trait_t4)*)*)?),+>)? redis::ToRedisArgs for $name$(<$($generic),+>)?
        $(
        where
            $($generic: serde::Serialize,)+
        )?
        {
            fn write_redis_args<W>(&self, out: &mut W)
            where
                W: ?Sized + redis::RedisWrite,
            {
                out.write_arg(serde_json::to_vec(self).unwrap().as_slice())
            }
        }
    }
}
